#!/usr/bin/env python3
# -*- coding:utf-8 -*-
## author : cypro666
## date   : 2014.5.23
"""
A duplicate data remover and data counter used for `simple counting tasks`,
not strong but fast and easy.
"""
import sys
from sys import getsizeof
from _collections import defaultdict

from .debug import time_meter
from .reports import CSVWriter

__all__ = ['DupRemover', 'DupCounter', 'DupCounterEx']


class DupRemover(set):
    """A simple duplicate remover, using like a set, output result to csv file"""
    __slots__ = ()
    def __init__(self):
        super().__init__()
    
    def __getitem__(self, key)->bool:
        return key in self
    
    def create_csv(self, filename, sort = False, reverse = False):
        sys.stdout.write('counter len : %d,  counter size : %d\n' % (len(self), getsizeof(self)))
        writer = CSVWriter(filename)
        writer.set_format('%s')
        if sort:
            for item in sorted(self, reverse = reverse):
                writer.write_row((item,)) 
        else:
            for item in self:
                writer.write_row((item,)) 
        writer.close()



def _create_csv(filename, counter, sort = False, reverse = False, ex = False):
    """Internal using"""
    writer = CSVWriter(filename)
    if not ex:
        writer.set_format('%d, %s\n')
        if sort:
            for k in sorted(counter, key=lambda k:counter[k], reverse = reverse):
                writer.write_row((counter[k], k)) 
        else:
            for k, v in counter.items():
                writer.write_row((v, k))
    else:
        writer.set_format('%s, %s, %s\n')
        if sort:
            for k in sorted(counter, key=lambda k:counter[k][0], reverse = reverse):
                writer.write_row((str(counter[k][0]), k, ''))
                for i in counter[k][1]:
                    writer.write_row((i.rstrip('\r\n'), '', ''))
        else:
            for k in counter:
                writer.write_row((str(counter[k][0]), k, ''))
                for i in counter[k][1]:
                    writer.write_row((i.rstrip('\r\n'), '', ''))
    writer.close()



class DupCounter(defaultdict):
    """A simple duplicate counter, output result to csv file"""
    __slots__ = ()
    def __init__(self):
        super().__init__(lambda:0)
    
    def add(self, key, inc = 1):
        self[key] += inc
    
    def create_csv(self, filename, sort = False, reverse = False):
        sys.stdout.write('counter len : %d,  counter size : %d\n' % (len(self), getsizeof(self)))
        _create_csv(filename, self, sort, reverse, False)



class DupCounterEx(dict):
    """A simple duplicate counter, can recored key and extra info about key"""
    __slots__ = ('__keymaker',)
    def __init__(self, key_maker):
        super().__init__()
        self.__keymaker = key_maker
        
    def add(self, rawkey, inc = 1):
        key = self.__keymaker(rawkey)
        try:
            self[key][0] += inc
            self[key][1].append(rawkey)
        except KeyError:
            self[key] = [inc, [rawkey]]
    
    def create_csv(self, filename, sort = False, reverse = False):
        sys.stdout.write('counter len : %d,  counter size : %d\n' % (len(self), getsizeof(self)))
        _create_csv(filename, self, sort, reverse, True)


@time_meter('dupcounter')
def test(N = 1000000):
    ''' test '''
    from random import randint, seed
    from time import time
    seed(time())
    
    t = time()
    dr = DupRemover()
    for i in range(N):
        k = chr(randint(0, 256))
        dr.add(k)
    dr.create_csv('test_dr.csv')
    sys.stdout.write('dr time: %.3fs\n' % (time()-t))
    
    t = time()
    dc = DupCounter()
    for i in range(N):
        k = chr(randint(0, 256))
        dc.add(k)
    dc.create_csv('test_dc.csv', True, True)
    sys.stdout.write('dc time: %.3fs\n' % (time()-t))
    
    t = time()
    dcx = DupCounterEx(lambda k:k)
    for i in range(N):
        k = chr(randint(0, 256))
        dcx.add(k)
    dcx.create_csv('test_dcx.csv', True, True)
    sys.stdout.write('dcx time: %.3fs\n' % (time()-t))










